#ifndef __SPS_ANALYZE_LIB2_H__
#define __SPS_ANALYZE_LIB2_H__

#include <stdint.h>

/* profile_idc */
#define BASELINE		66           /* !< YUV 4:2:0/8  "Baseline" */
#define MAIN			77           /* !< YUV 4:2:0/8  "Main" */
#define EXTENDED		88           /* !< YUV 4:2:0/8  "Extended" */
#define FREXT_HP		100          /* !< YUV 4:2:0/8  "High" */
#define FREXT_Hi10P		110          /* !< YUV 4:2:0/10 "High 10" */
#define FREXT_Hi422		122          /* !< YUV 4:2:2/10 "High 4:2:2" */
#define FREXT_Hi444		244          /* !< YUV 4:4:4/12 "High 4:4:4" */
#define FREXT_CAVLC444	44           /* !< YUV 4:4:4/14 "CAVLC 4:4:4" */

#define lib2H264_get_1_bits(bs) lib2H264_get_n_bits(bs, 1)
#define CHECK_PARAM(code, n) {if (code != n) return 0; }

typedef struct __BITSTREAM_CTL {
    uint8_t *Rdstr;   /* 码流缓冲区首地址 */
    uint8_t *Rdcur;   /* 当前读取的地址 */
    uint8_t *Rdmax;   /* 码流缓冲区最大的地址 */
    uint32_t b_num;   /* 码字缓存中包含的有效位数 */
    uint32_t k_cache; /* 码字缓存 4个字节 32位 */
} BITSTREAM_CTL;

typedef struct {
    uint16_t width;
    uint16_t height;
    float frame_rate;
} VIDEO_ES_INFO;

/***
 * Sequence parameter set 
 * 可参考H264标准第7节和附录D E
 */
#define Extended_SAR 255

typedef struct __hrd_parameters_{
    int cpb_cnt_minus1;                         //0 ue(v)
    int bit_rate_scale;                         //0 u(4)
    int cpb_size_scale;                         //0 u(4)
    int bit_rate_value_minus1[16];              //0 ue(v)
    int cpb_size_value_minus1[16];              //0 ue(v)
    int cbr_flag[16];                           //0 u(1)
    int initial_cpb_removal_delay_length_minus1;//0 u(5)
    int cpb_removal_delay_length_minus1;        //0 u(5)
    int dpb_output_delay_length_minus1;         //0 u(5)
    int time_offset_length;                     //0 u(5)
}_hrd_parameters_t;

typedef struct __vui_parameters_{
    int aspect_ratio_info_present_flag;         //0 u(1) 
    // if( aspect_ratio_info_present_flag ) {
        int aspect_ratio_idc;                   //0 u(8) 
            // if( aspect_ratio_idc = = Extended_SAR ) {
            int sar_width;                      //0 u(16) 
            int sar_height;                     //0 u(16) 
            // }
    // }
    int overscan_info_present_flag;             //0 u(1) 
    // if( overscan_info_present_flag )
        int overscan_appropriate_flag;          //0 u(1) 
    int video_signal_type_present_flag; //0 u(1) 
    // if( video_signal_type_present_flag ) {
        int video_format;                       //0 u(3) 
        int video_full_range_flag;              //0 u(1) 
        int colour_description_present_flag;    //0 u(1) 
        // if( colour_description_present_flag ) {
            int colour_primaries;               //0 u(8) 
            int transfer_characteristics;       //0 u(8) 
            int matrix_coefficients;            //0 u(8) 
        // }
    // }
    int chroma_loc_info_present_flag;           //0 u(1) 
    // if( chroma_loc_info_present_flag ) {
        int chroma_sample_loc_type_top_field;   //0 ue(v) 
        int chroma_sample_loc_type_bottom_field;//0 ue(v) 
    // }
    int timing_info_present_flag;               //0 u(1) 
    // if( timing_info_present_flag ) {
        uint32_t num_units_in_tick;             //0 u(32) 
        uint32_t time_scale;                    //0 u(32) 
        int fixed_frame_rate_flag;              //0 u(1) 
    // }
    int nal_hrd_parameters_present_flag;        //0 u(1)
    // if( nal_hrd_parameters_present_flag )
        _hrd_parameters_t nal_hrd_parameters;
    // }
    int vcl_hrd_parameters_present_flag;        //0 u(1)
    // if( vcl_hrd_parameters_present_flag )
        _hrd_parameters_t vcl_hrd_parameters;
    // }
    // if( nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag )
        int low_delay_hrd_flag;                 //0 u(1)
    int pic_struct_present_flag;                //0 u(1)
    int bitstream_restriction_flag;             //0 u(1)
    // if( bitstream_restriction_flag ) {
        int motion_vectors_over_pic_boundaries_flag;  //0 ue(v)
        int max_bytes_per_pic_denom;                  //0 ue(v)
        int max_bits_per_mb_denom;                    //0 ue(v)
        int log2_max_mv_length_horizontal;            //0 ue(v)
        int log2_max_mv_length_vertical;              //0 ue(v)
        int num_reorder_frames;                       //0 ue(v)
        int max_dec_frame_buffering;                  //0 ue(v)
    // }
}_vui_parameters_t;
 
typedef struct __seq_parameter_set_data_{
    int profile_idc;                            //0 u(8)
    int constraint_set0_flag;                   //0 u(1)
    int constraint_set1_flag;                   //0 u(1)
    int constraint_set2_flag;                   //0 u(1)
    int constraint_set3_flag;                   //0 u(1)
    int reserved_zero_4bits;                    //0 u(1) + u(1) + u(2)              
    int level_idc;
    int seq_parameter_set_id;				    //0 ue(v)
    // if( profile_idc == 100||110||122||244||44||83||86||118||128||138||139||134||135 ) {
        int	chroma_format_idc;				    //0 ue(v)
        // if( chroma_format_idc == 3 )
            int	separate_colour_plane_flag;	    //0 u(1)
        // }
        int	bit_depth_luma_minus8;				//0 ue(v) 
        int	bit_depth_chroma_minus8;			//0 ue(v) 
        int	qpprime_y_zero_transform_bypass_flag;//0 u(1) 
        int seq_scaling_matrix_present_flag;	//0 u(1)
        // if( seq_scaling_matrix_present_flag )
            int	seq_scaling_list_present_flag[12];
            int	UseDefaultScalingMatrix4x4Flag[6];
            int	UseDefaultScalingMatrix8x8Flag[6];
            int	ScalingList4x4[6][16];
            int	ScalingList8x8[6][64];
        // }
    // }
    int log2_max_frame_num_minus4;				//0	ue(v)
    int pic_order_cnt_type;						//0 ue(v)
    // if( pic_order_cnt_type == 0 )
        int log2_max_pic_order_cnt_lsb_minus4;  //0 ue(v)
    // else if( pic_order_cnt_type == 1 ) {
        int	delta_pic_order_always_zero_flag;   //0 u(1)
        int	offset_for_non_ref_pic;             //0 se(v)
        int	offset_for_top_to_bottom_field;     //0 se(v)
        int	num_ref_frames_in_pic_order_cnt_cycle; //0 ue(v)	
        int	offset_for_ref_frame_array[16];     //0 se(v)
    // }
    int num_ref_frames;                         //0 ue(v)
    int	gaps_in_frame_num_value_allowed_flag;   //0 u(1)
    int	pic_width_in_mbs_minus1;                //0 ue(v)
    int	pic_height_in_map_units_minus1;         //0 u(1)
    int	frame_mbs_only_flag;  	                //0 u(1) 
    // if( !frame_mbs_only_flag )
        int	mb_adaptive_frame_field_flag;       //0 u(1) 
    int	direct_8x8_inference_flag;              //0 u(1) 
    int	frame_cropping_flag;                    //0 u(1)
    // if( frame_cropping_flag ) {
        int	frame_crop_left_offset;             //0 ue(v)
        int	frame_crop_right_offset;            //0 ue(v)
        int	frame_crop_top_offset;              //0 ue(v)
        int	frame_crop_bottom_offset;	        //0 ue(v)
    // }
    int vui_parameters_present_flag;            //0 u(1)
    // if( vui_parameters_present_flag )
        _vui_parameters_t vui_parameters;
}_seq_parameter_set_data_t;

uint32_t lib2H264_get_n_bits(BITSTREAM_CTL *bs, uint32_t n);
uint32_t lib2H264_get_uev(BITSTREAM_CTL *bs, uint32_t *info);
uint32_t lib2H264_get_uev_code(BITSTREAM_CTL *bs);
uint32_t lib2H264_read_sev_code(BITSTREAM_CTL *bs);

void lib2H264_decode_scaling_list(BITSTREAM_CTL *bs, int32_t size);
void lib2H264_decode_scaling_mtx(BITSTREAM_CTL *bs);

void lib2H264_init_bitstream(BITSTREAM_CTL *bs, uint8_t *buffer, int32_t size);
int32_t lib2H264_get_vui_parameters(BITSTREAM_CTL *bs, _vui_parameters_t *vui_data);
int32_t lib2H264_InterpretSPS(BITSTREAM_CTL *bs, _seq_parameter_set_data_t *sps_data);
int32_t lib2H264_get_sps_info(uint8_t *buffer, uint32_t length, _seq_parameter_set_data_t *sps_data);

int32_t sps_analyze_lib2_demo(int argc, const char *argv[]);
#endif /* __SPS_ANALYZE_MODE2_H__ */
